﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace VectorEditor
{
    public interface IDocumentControl
    {
        EditorController Controller { get; }
		Document Document { get; }
        PointF ScreenToDocumentCoordinates(Point screenCoord);
        Point DocumentToScreenCoordinates(PointF documentCoord);
        void Refresh(Action<Graphics> drawFunc);
    }
	public partial class DocumentView : UserControl, IDocumentControl
	{
        public bool IsModified { get; private set; }
		public DocumentView()
		{
			InitializeComponent();
			SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
		}

        private bool CanEdit()
        {
            return Tool != null && Controller != null;
        }

		private Document document;
		public Document Document
		{
			get 
			{
				return document; 
			}
			set
			{
                IsModified = false;
				document = value;
				if (document != null)
				{
					document.ContentChanged += new ContentChangedEventHandler(document_ContentChanged);
                    Controller = new EditorController(document);
				}
				UpdateScrollBars();
				Refresh();
			}
		}

		void document_ContentChanged()
		{
            IsModified = true;
			//throw new NotImplementedException();
            Refresh();
		}

		private void UpdateScrollBars()
		{
			hScrollPanel.Visible = false;
			vScrollBar.Visible = false;

			SetScrollBarPass();
			SetScrollBarPass();
			hScrollBar.Width = this.ClientRectangle.Width;
		}

		private void SetScrollBarPass()
		{
			if (document == null)
				return;
			if (document.Height > this.ClientRectangle.Height)
			{
				vScrollBar.Visible = true;
				vScrollBar.Minimum = 0;
				vScrollBar.Maximum = (int)document.Height;// -this.ClientRectangle.Height;
				vScrollBar.LargeChange = this.ClientRectangle.Height;
			}
			if (document.Width > this.ClientRectangle.Width)
			{
				hScrollPanel.Visible = true;
				hScrollBar.Minimum = 0;
				hScrollBar.Maximum = (int)document.Width;// -this.ClientRectangle.Width;
				hScrollBar.LargeChange = this.ClientRectangle.Width;
			}
		}

		private void DocumentView_Paint(object sender, PaintEventArgs e)
		{
			e.Graphics.FillRectangle(SystemBrushes.WindowFrame, this.ClientRectangle);

			e.Graphics.Transform = new Matrix(1, 0, 0, 1, -hScrollBar.Value, -vScrollBar.Value);
			DrawDocument(e.Graphics);
			if (Tool != null)
				Tool.DrawOverlay(e.Graphics);

            if (clientDrawFunc != null)
            {
                clientDrawFunc(e.Graphics);
                clientDrawFunc = null;
            }
		}

		private void DrawDocument(Graphics g)
		{			
			if (document == null)
				return;
			RectangleF documentRect = new RectangleF(0, 0, document.Width, document.Height);
			g.FillRectangle(Brushes.White, documentRect);
			g.SetClip(documentRect);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            foreach (var prim in document.Primitives)
            {
				Primitive p = prim;
				if (Tool != null)
				{
					p = Tool.ReplacePrimitive(p);
				}
				p.Draw(g);
            }
		}

		private void vScrollBar_ValueChanged(object sender, EventArgs e)
		{
			this.Refresh();
		}

		private void DocumentView_Resize(object sender, EventArgs e)
		{
			UpdateScrollBars();
		}

        internal Tool Tool { get; set; }
        public EditorController Controller { get; private set; }

        private void DocumentView_MouseDown(object sender, MouseEventArgs e)
        {
            if (CanEdit())
            {
                Tool.HandleMouseDown(this, e.Location, e.Button);
            }
        }

        private void DocumentView_MouseMove(object sender, MouseEventArgs e)
        {
            if (CanEdit())
            {
                Tool.HandleMouseMove(this, e.Location, e.Button);
            }
        }

        private void DocumentView_MouseUp(object sender, MouseEventArgs e)
        {
            if (CanEdit())
            {
                Tool.HandleMouseUp(this, e.Location, e.Button);
            }
        }

        #region IDocumentControl Members


        public PointF ScreenToDocumentCoordinates(Point point)
        {
            return new PointF(point.X + hScrollBar.Value, point.Y + vScrollBar.Value);
        }

        public Point DocumentToScreenCoordinates(PointF documentCoord)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IDocumentControl Members

        Action<Graphics> clientDrawFunc = null;

        public void Refresh(Action<Graphics> drawFunc)
        {
            clientDrawFunc = drawFunc;
            Refresh();
        }

        #endregion

        internal void Save(string currentFilename)
        {
            throw new NotImplementedException();
        }
    }
}
